﻿using System;
using comm;
using Microsoft.VisualStudio.Debugger.Interop;
using Red.Scripts.Debugger.Defines;

namespace Red.Scripts.Debugger.Remote.Debugger
{
    // This class represents a document context to the debugger. A document context represents a location within a source file. 
    class DocumentContext : IDebugDocumentContext2
    {
        private Breakpoint.Location _location;

        public ScriptStackFrame Frame { get; private set; }

        #region C-Tor

        public DocumentContext( ScriptStackFrame frame )
        {
            Frame = frame;
            _location = Breakpoint.Location.CreateFromRedEngine( frame.breakpoint );
        }

        #endregion C-Tor

        #region IDebugDocumentContext2 Members

        // Compares this document context to a given array of document contexts.
        int IDebugDocumentContext2.Compare( enum_DOCCONTEXT_COMPARE Compare, IDebugDocumentContext2[] rgpDocContextSet, uint dwDocContextSetLen, out uint pdwDocContext )
        {
            dwDocContextSetLen = 0;
            pdwDocContext = 0;

            return Constants.E_NOTIMPL;
        }

        // Retrieves a list of all code contexts associated with this document context.
        // The engine sample only supports one code context per document context and 
        // the code contexts are always memory addresses.
        int IDebugDocumentContext2.EnumCodeContexts( out IEnumDebugCodeContexts2 ppEnumCodeCxts )
        {
            ppEnumCodeCxts = null;

            return Constants.E_NOTIMPL;
        }

        // Gets the document that contains this document context.
        // This method is for those debug engines that supply documents directly to the IDE. Since the sample engine
        // does not do this, this method returns E_NOTIMPL.
        int IDebugDocumentContext2.GetDocument( out IDebugDocument2 ppDocument )
        {
            ppDocument = null;

            return Constants.E_NOTIMPL;
        }

        // Gets the language associated with this document context.
        // The language for this sample is always C++
        int IDebugDocumentContext2.GetLanguageInfo( ref string pbstrLanguage, ref Guid pguidLanguage )
        {
            pbstrLanguage = Language.Name;
            pguidLanguage = Language.Guid;

            return Constants.S_OK;
        }

        // Gets the displayable name of the document that contains this document context.
        int IDebugDocumentContext2.GetName( enum_GETNAME_TYPE gnType, out string pbstrFileName )
        {
            pbstrFileName = _location.File;

            return Constants.S_OK;
        }

        // Gets the source code range of this document context.
        // A source range is the entire range of source code, from the current statement back to just after the previous s
        // statement that contributed code. The source range is typically used for mixing source statements, including 
        // comments, with code in the disassembly window.
        // Since this engine does not support the disassembly window, this is not implemented.
        int IDebugDocumentContext2.GetSourceRange( TEXT_POSITION[] pBegPosition, TEXT_POSITION[] pEndPosition )
        {
            throw new NotImplementedException( "This method is not implemented" );
        }

        // Gets the file statement range of the document context.
        // A statement range is the range of the lines that contributed the code to which this document context refers.
        int IDebugDocumentContext2.GetStatementRange( TEXT_POSITION[] pBegPosition, TEXT_POSITION[] pEndPosition )
        {
            pBegPosition[ 0 ].dwColumn = _location.Column;
            pBegPosition[ 0 ].dwLine = _location.VisualStudioLine;

            pEndPosition[ 0 ].dwColumn = _location.EndColumn;
            pEndPosition[ 0 ].dwLine = _location.VisualStudioLine;

            return Constants.S_OK;
        }

        // Moves the document context by a given number of statements or lines.
        // This is used primarily to support the Autos window in discovering the proximity statements around 
        // this document context. 
        int IDebugDocumentContext2.Seek( int nCount, out IDebugDocumentContext2 ppDocContext )
        {
            ppDocContext = null;

            return Constants.E_NOTIMPL;
        }

        #endregion
    }
}
